Tutorial - Setup Single-SPA with Angular and React

May 01, 2021

Remark

This tutorial is written with create-single-spa script v.2.2.2. To follow along with this tutorial setup your folder structure like this.

my-first-single-spa
└─── angular-app
└─── react-app
└─── root-config

Step 1: create Single-SPA root-config

Open a new Terminal at the root of your project (in the my-first-single-spa folder). Then run npx create-single-spa --moduleType root-config --layout. This will start a command-line dialog where you have to insert some data.

- directory to create root-config: root-config
- package manager: npm
- use TypeScript: no
- organization name: org1

Thats all for creating the root-config. If you now look into the root-config-folder you should see the created files.

Step 2: create Angular app

Configuring Single-SPA in a way to work seamless with Angular is quite a challenge but if you follow the further outlined steps it shouldn’t be a problem.
Open a Terminal in the root-folder and type

npx create-single-spa --framework=angular

This will start a command-line- dialog again and I had answered it with the following properties.

- directory to create angular app: angular-app
- project name: angular-mfe
- use Angular Routing: yes
- choose stylesheet format: css
- use Angular routing (yes this is redundant but required by the CLI): yes
- use BrowserAnimationsModule: yes 

Now you have to do some configurations to connect Single-SPA and Angular. First navigate into your newly created Angular application (here: cd angular-app/angular-mfe) and run npm install. Yes this seems like a redundant step as well but you have to do it since the create-single-spa-script does not do it.
After this you have to configure the Angular Routing. Open app-routing.module.ts and add

providers: [{ provide: APP_BASE_HREF, useValue: '/' }]

to the NgModule. Then locate the route-Array at the top of the file and add

{ path: '**', component: EmptyRouteComponent }

to the array. Now switch to app.module.ts and add EmptyRouteComponent to the declarations-Array in the NgModule.
Now you have to go back to the root-config and register the Angular-application. So open root-config/src/index.ejs and uncomment the line that imports zone.js. In my version this is located at line 61 but if you cant find it, hit CTRL+f and search for zone or angular.
Now you need to locate the import-map for registering applications in the index.ejs-file. By default this import-map contains the single-spa welcome page so you have to look for this line.

"@single-spa/welcome": "https://unpkg.com/single-spa-welcome/dist/single-spa-welcome.js"

Register your Angular-application by adding the following property to the import-object.

"@org1/angular": "http://localhost:4200/main.js"

The final import-map should look like this. 64f426078e13eb072b50b479607d436e.png

Now open microfrontend-layout.html which is next to index.ejs and add our Angular-application inside the <route>-tag.

<route default>
    <application name="@org1/angular"></application>
</route>

Alright, everything is set up so lets see if everything works as expected. Open a new terminal and start the root-config by running

cd root-config
npm run start

Of course you need to start the Angular-application as well. So another terminal.

cd angular-app
npm run serve:single-spa:angular-mfe

Open your browser and go to http://localhost:9000. There you should see the angular default template or anything that you have specified in the app-component.

Step 3: create React app

As with root-config and Angular-application we use the create-single-spa-script.

npx create-single-spa --framework=react

As well a command-line dialog

- directory to create angular app: react-app
- choose package manager: npm
- use TypeScript: yes
- organization name: org1
- project name: react

As with the Angular-application you have to register the React-app. So go to root-config/src/index.ejs, locate the import map where you registered the Angular-app in the previous step and add the following property to the import-map.

"@org1/react": "http://localhost:8080/org1-react.js"

For the React-app to work you have to state the react dependencies as shared dependencies. For this you need to locate another import-map inside index.ejs. This time its the import-map for shared dependencies. Since single-spa is a shared dependency by default yo can simply look for a line that looks like

"single-spa": "https://cdn.jsdelivr.net/npm/single-spa@5.9.0/lib/system/single-spa.min.js",

After you found it add react and react-dom as shared dependencies by adding these two properties after the single-spa-dependency

"react": "https://cdn.jsdelivr.net/npm/react@16.13.1/umd/react.production.min.js",
"react-dom": "https://cdn.jsdelivr.net/npm/react-dom@16.13.1/umd/react-dom.production.min.js"

Finally you have to introduce the React-app in the markup as well. Open microfrontend-layout.html and add the React-app as you have done it with the Angular app. The final result should look like

<route default>
	<application name="@org1/angular"></application>
	<application name="@org1/react"></application>
</route>

Start the React-app by running npm run start in another terminal. Refresh localhost:9000 and you should see an Angular-application coexisting next to a React-app.